package com.mall.czlr.app.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.mall.czlr.app.common.Const;
import com.mall.czlr.app.dao.UserMapper;
import com.mall.czlr.app.model.Token;
import com.mall.czlr.app.model.User;
import com.mall.czlr.app.service.ITokenService;
import com.mall.czlr.app.service.IUserService;
import com.mall.czlr.app.vo.RespUserVo;
import com.mall.czlr.base.common.PageObj;
import com.mall.czlr.base.exception.BaseException;
import com.mall.czlr.base.exception.GlobalException;
import com.mall.czlr.base.service.impl.BaseServiceImpl;
import com.mall.czlr.base.util.Assert;
import com.mall.czlr.base.util.CommonUtil;
import com.mall.czlr.base.util.PasswordHash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implements IUserService {

    private final ITokenService tokenService;

    @Autowired
    public UserServiceImpl(ITokenService tokenService) {
        this.tokenService = tokenService;
    }

    @Override
    public Map<String, Object> register(String username, String password) throws Exception {
        User user = this.selectOne(new EntityWrapper<User>().eq("username", username));
        Assert.isNotNull(BaseException.ERROR_EXISTS, "该用户名已被使用", user);

        String pwd = PasswordHash.createHash(password);

        Long now = CommonUtil.time();

        user = new User();
        user.setUsername(username);
        user.setPassword(pwd);
        user.setNickname(username);
        user.setAvatar("");
        user.setCreateTime(now);
        user.setUpdateTime(now);

        user = this.insertReturn(user);

        HashMap<String, Object> map = new HashMap<>();
        map.put("user", new RespUserVo(user));

        return map;
    }

    @Override
    public Map<String, Object> login(String username, String password) throws Exception {
        User user = this.selectOne(new EntityWrapper<User>().eq("username", username));
        Assert.isNull(BaseException.ERROR_NOT_EXISTS, "用户不存在", user);

        if (!PasswordHash.validatePassword(password, user.getPassword())) {
            throw new GlobalException(BaseException.ERROR_NOT_ALLOWED, "密码错误");
        }

        Long now = CommonUtil.time();

        Token token = new Token();
        token.setToken(Token.makeToken());
        token.setStatus(1);
        token.setUserId(user.getId());
        token.setUserType(Const.USER_TYPE_USER);
        token.setCreateTime(now);
        token.setUpdateTime(now);

        token = tokenService.insertReturn(token);

        HashMap<String, Object> map = new HashMap<>();
        map.put("user", new RespUserVo(user));
        map.put("token", token.getToken());

        return map;
    }

    @Override
    public void logout(String token) {
        tokenService.delete(new EntityWrapper<Token>().eq("token", token));
    }

    @Override
    public Map<String, Object> getUserInfo(Long userId) {
        User user = this.selectOne(new EntityWrapper<User>().eq("id", userId));
        Assert.isNull(BaseException.ERROR_NOT_EXISTS, "用户不存在", user);

        HashMap<String, Object> map = new HashMap<>();
        map.put("user", new RespUserVo(user));

        return map;
    }

    @Override
    public void updateUserInfo(Long userId, String nickname, String avatar) {
        User user = this.selectOne(new EntityWrapper<User>().eq("id", userId));
        Assert.isNull(BaseException.ERROR_NOT_EXISTS, "用户不存在", user);

        user.setNickname(nickname);
        user.setAvatar(avatar);
        this.updateById(user);
    }

    @Override
    public Map<String, Object> getUserList(PageObj obj) {
        Page<User> o = this.selectPage(new Page<>(obj.getPage(), obj.getLimit()), null);

        List<User> userList = o.getRecords();

        HashMap<String, Object> map = new HashMap<>();
        map.put("list", userList);
        map.put("total", o.getTotal());
        map.put("size", o.getSize());

        return map;
    }
}
